#include <stdio.h> 
#include <stdlib.h> 
#include <string.h>
#include "wm_mem.h"
#include "pvmp3_dec.h"
#include "psram.h"

#include "../user_config.h"

#if USE_PSRAM_AUDIO
#define MEM_MALLOC  dram_heap_malloc
#define MEM_FREE    dram_heap_free
#else
#define MEM_MALLOC  tls_mem_alloc
#define MEM_FREE    tls_mem_free
#endif

#define TAG                    "ad_pvmp3"

#ifndef CHECK_RET_TAG_WITH_RET
#define CHECK_RET_TAG_WITH_RET(x, ret) \
	do { \
		if (!(x)) { \
			printf("%s, %d fail", __FUNCTION__, __LINE__); \
			return ret; \
		}\
	} while (0)
#endif

#ifndef CHECK_RET_TAG_WITH_GOTO
#define CHECK_RET_TAG_WITH_GOTO(x, label) \
	do { \
		if (!(x)) { \
			printf("%s, %d fail", __FUNCTION__, __LINE__); \
			goto label; \
		}\
	} while (0)
#endif




struct ad_pvmp3_priv *priv = NULL;
//static char g_dbuf[28000];
int ad_pvmp3_open(void)
{
    uint32_t msize;
    void *dbuf = NULL, *obuf = NULL;
    tPVMP3DecoderExternal *config;

    priv = (struct ad_pvmp3_priv *)MEM_MALLOC(sizeof(struct ad_pvmp3_priv));
    CHECK_RET_TAG_WITH_RET(priv, -1);

    config = &priv->config;
    msize  = pvmp3_decoderMemRequirements();
	//printf("pvmp3_decoderMemRequirements %d\n", msize);
    dbuf   = MEM_MALLOC(msize);
    obuf   = MEM_MALLOC(PVMP3DEC_OBUF_SIZE);
    CHECK_RET_TAG_WITH_GOTO(dbuf && obuf, err);

    pvmp3_InitDecoder(config, dbuf);
    config->crcEnabled    = false;
    config->equalizerType = flat;
    config->pOutputBuffer = (int16*)obuf;

    priv->obuf = obuf;
    priv->dbuf = dbuf;
    return 0;

err:
    MEM_FREE(obuf);
    MEM_FREE(dbuf);
    MEM_FREE(priv);
    return -1;
}

int ad_pvmp3_decode(unsigned char* data, int len, unsigned char **out, int *outlen, int *chans, int *samplingRate)
{
    int ret = 0;
    ERROR_CODE ecode;
    tPVMP3DecoderExternal *config;
    int rc, channel, bits = 16;

    config = &priv->config;
    config->inputBufferMaxLength     = 0;
    config->inputBufferUsedLength    = 0;
    config->pInputBuffer             = data;
    config->inputBufferCurrentLength = len;
    config->outputFrameSize          = PVMP3DEC_OBUF_SIZE / sizeof(int16_t);

    ecode = pvmp3_framedecoder(config, priv->dbuf);
    if (!((ecode == NO_DECODING_ERROR) &&
          config->outputFrameSize && config->num_channels && config->samplingRate)) {
        printf("---> ecode = %d, frame size = %d, ch = %d, rate = %d.\n", ecode,
            config->outputFrameSize, config->num_channels, config->samplingRate);
        return ecode;
    }
	if(samplingRate)
	{
		*samplingRate = config->samplingRate;
	}
	if(chans)
	{
		*chans = config->num_channels;
	}
	rc = config->outputFrameSize * 2;
	if(outlen)
	{
		*outlen = rc;
	}
	if(out)
	{
    	//memcpy(out, config->pOutputBuffer, rc);
    	*out = config->pOutputBuffer;
	}
    ret = config->inputBufferUsedLength;;

quit:
    return ret;
}

int ad_pvmp3_close(void)
{
	if(priv)
	{
		if(priv->obuf)
		{
			MEM_FREE(priv->obuf);
		}
		if(priv->dbuf)
		{
			pvmp3_closeDecoder(priv->dbuf);
			MEM_FREE(priv->dbuf);
		}
    	MEM_FREE(priv);
	}
	return 0;
}

